/*-------------------------------------------------------------------------
 *
 * brin_xlog.h
 *	  POSTGRES BRIN 访问 XLOG 定义
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/access/brin_xlog.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef BRIN_XLOG_H
#define BRIN_XLOG_H

#include "access/xlogreader.h"
#include "lib/stringinfo.h"
#include "storage/bufpage.h"
#include "storage/itemptr.h"
#include "storage/relfilenode.h"
#include "utils/relcache.h"


/*
 * BRIN 的 WAL 操作的 WAL 记录定义
 *
 * XLOG 允许在日志记录的高 4 位 xl_info 字段中存储一些信息。
 */
#define XLOG_BRIN_CREATE_INDEX		0x00
#define XLOG_BRIN_INSERT			0x10
#define XLOG_BRIN_UPDATE			0x20
#define XLOG_BRIN_SAMEPAGE_UPDATE	0x30
#define XLOG_BRIN_REVMAP_EXTEND		0x40
#define XLOG_BRIN_DESUMMARIZE		0x50

#define XLOG_BRIN_OPMASK			0x70
/*
 * 当我们在新页面上插入第一个项目时，我们在 redo 中恢复整个页面。
 */
#define XLOG_BRIN_INIT_PAGE		0x80

/*
 * 这是我们需要了解的有关 BRIN 索引创建的信息。
 *
 * 备份块 0：元页面
 */
typedef struct xl_brin_createidx
{
	BlockNumber pagesPerRange;
	uint16		version;
} xl_brin_createidx;
#define SizeOfBrinCreateIdx (offsetof(xl_brin_createidx, version) + sizeof(uint16))

/*
 * 这是我们需要了解的有关 BRIN 元组插入的信息
 *
 * 备份块 0：主页面，块数据是新的 BrinTuple。
 * 备份块 1：反向映射页面
 */
typedef struct xl_brin_insert
{
	BlockNumber heapBlk;

	/* 更新反向映射所需的额外信息 */
	BlockNumber pagesPerRange;

	/* 在主页面中插入元组的偏移量 */
	OffsetNumber offnum;
} xl_brin_insert;

#define SizeOfBrinInsert	(offsetof(xl_brin_insert, offnum) + sizeof(OffsetNumber))

/*
 * 跨页面更新与插入相同，但还存储有关旧元组的信息。
 *
 * 在 xl_brin_insert 中：
 * 备份块 0：新页面，块数据包括新的 BrinTuple。
 * 备份块 1：反向映射页面
 *
 * 并且额外：
 * 备份块 2：旧页面
 */
typedef struct xl_brin_update
{
	/* 旧页面上旧元组的偏移量 */
	OffsetNumber oldOffnum;

	xl_brin_insert insert;
} xl_brin_update;

#define SizeOfBrinUpdate	(offsetof(xl_brin_update, insert) + SizeOfBrinInsert)

/*
 * 这是我们需要了解的有关 BRIN 元组同页更新的信息
 *
 * 备份块 0：更新页面，块数据为新的 BrinTuple
 */
typedef struct xl_brin_samepage_update
{
	OffsetNumber offnum;
} xl_brin_samepage_update;

#define SizeOfBrinSamepageUpdate		(sizeof(OffsetNumber))

/*
 * 这是我们需要了解的有关反向映射扩展的信息
 *
 * 备份块 0：元页面
 * 备份块 1：新的反向映射页面
 */
typedef struct xl_brin_revmap_extend
{
	/*
	 * XXX：这实际上是多余的 - 块编号作为备份块 1 的一部分存储。
	 */
	BlockNumber targetBlk;
} xl_brin_revmap_extend;

#define SizeOfBrinRevmapExtend	(offsetof(xl_brin_revmap_extend, targetBlk) + \
								 sizeof(BlockNumber))

/*
 * 这是我们需要了解的有关范围去概括的信息
 *
 * 备份块 0：反向映射页面
 * 备份块 1：常规页面
 */
typedef struct xl_brin_desummarize
{
	BlockNumber pagesPerRange;
	/* 设置为无效的页面编号位置 */
	BlockNumber heapBlk;
	/* 常规索引页面中要删除的项目偏移量 */
	OffsetNumber regOffset;
} xl_brin_desummarize;

#define SizeOfBrinDesummarize	(offsetof(xl_brin_desummarize, regOffset) + \
								 sizeof(OffsetNumber))


extern void brin_redo(XLogReaderState *record);
extern void brin_desc(StringInfo buf, XLogReaderState *record);
extern const char *brin_identify(uint8 info);
extern void brin_mask(char *pagedata, BlockNumber blkno);

#endif							/* BRIN_XLOG_H */
